#include <iostream>
#include <vector>
using namespace std;
// 思想：先划分在遍历是否可行
// T : nlogn S: 1
// 检查是否满足划分为M段的条件
bool check(vector<int>& nums, int M, int x) {
	int cnt = 1;   // 当前已划分的段数
	int sum = 0;   // 当前段的和
	
	for (int num : nums) {
		if (sum + num <= x) {   // 将当前元素加入当前段
			sum += num;
		} else {   // 当前元素应该属于下一段
			cnt++;
			sum = num;
		}
	}
	
	return cnt <= M;   // 返回是否满足划分为M段的条件
}

int splitArray(vector<int>& nums, int M) {
	int maxNum = 0;   // 数列的最大值
	int sum = 0;      // 数列的总和
	
	for (int num : nums) {
		maxNum = max(maxNum, num);   // 更新最大值
		sum += num;                  // 累加总和
	}
	
	int left = maxNum;   // 和的最大值的下界，即最大值
	int right = sum;     // 和的最大值的上界，即总和
	
	while (left < right) {   // 二分查找
		int mid = left + (right - left) / 2;   // 中间值
		if (check(nums, M, mid)) {   // 检查中间值是否满足划分为M段的条件
			right = mid;    // 更新上界
		} else {
			left = mid + 1;   // 更新下界
		}
	}
	
	return left;   // 返回和的最大值的最小值
}

int main() {
	int N, M;
	cin >> N >> M;
	
	vector<int> nums(N);
	for (int i = 0; i < N; i++) {
		cin >> nums[i];
	}
	
	int result = splitArray(nums, M);
	cout << result << endl;
	
	return 0;
}
